package com.summer.filesync.manager.service;

import com.summer.filesync.database.dao.FileMetadataDAO;
import com.summer.filesync.model.manager.FileDifference;
import com.summer.filesync.model.manager.FileVersion;
import com.summer.filesync.util.FileUtils;
import com.summer.filesync.util.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/** 文件版本管理服务 提供文件版本控制功能 */
public class FileVersionService {
  private static final Logger logger = Logger.getLogger(FileVersionService.class);

  private final FileMetadataDAO fileMetadataDAO;
  private final Map<String, List<FileVersion>> versionCache;
  private final String versionsDirectory;

  public FileVersionService(FileMetadataDAO fileMetadataDAO) {
    this.fileMetadataDAO = fileMetadataDAO;
    this.versionCache = new ConcurrentHashMap<>();
    this.versionsDirectory =
        System.getProperty("user.home")
            + File.separator
            + ".filesync"
            + File.separator
            + "versions";

    // 确保版本目录存在
    try {
      Files.createDirectories(Paths.get(versionsDirectory));
    } catch (IOException e) {
      logger.error("无法创建版本目录: " + versionsDirectory, e);
    }
  }

  /** 创建文件版本 */
  public FileVersion createVersion(String filePath, String comment) {
    logger.debug("为文件创建版本: " + filePath);

    try {
      Path sourceFile = Paths.get(filePath);
      if (!Files.exists(sourceFile) || Files.isDirectory(sourceFile)) {
        logger.warn("文件不存在或为目录: " + filePath);
        return null;
      }

      // 计算文件校验和
      String checksum = FileUtils.calculateSHA256(filePath);
      long fileSize = Files.size(sourceFile);

      // 检查是否与最新版本相同
      List<FileVersion> existingVersions = getVersionHistory(filePath);
      if (!existingVersions.isEmpty()) {
        FileVersion latestVersion = existingVersions.get(0);
        if (checksum.equals(latestVersion.getChecksum())) {
          logger.info("文件内容未变化，跳过版本创建: " + filePath);
          return latestVersion;
        }
      }

      // 创建新版本
      FileVersion version = new FileVersion(filePath, comment, fileSize, checksum);

      // 备份文件
      String backupPath = createBackupFile(sourceFile, version.getVersionId());
      version.setBackupPath(backupPath);

      // 将最新版本标记为当前版本
      version.setCurrent(true);

      // 更新其他版本的当前状态
      for (FileVersion existingVersion : existingVersions) {
        existingVersion.setCurrent(false);
      }

      // 添加到缓存
      List<FileVersion> versions = versionCache.computeIfAbsent(filePath, k -> new ArrayList<>());
      versions.add(0, version); // 插入到开头，保持时间顺序

      logger.info("成功创建文件版本: " + filePath + " -> " + version.getVersionId());
      return version;

    } catch (Exception e) {
      logger.error("创建文件版本失败: " + filePath, e);
      return null;
    }
  }

  /** 获取文件版本历史 */
  public List<FileVersion> getVersionHistory(String filePath) {
    List<FileVersion> versions = versionCache.get(filePath);
    if (versions == null) {
      // 从磁盘加载版本信息（简化实现，实际应从数据库加载）
      versions = loadVersionsFromDisk(filePath);
      versionCache.put(filePath, versions);
    }

    return new ArrayList<>(versions);
  }

  /** 恢复文件到指定版本 */
  public boolean restoreVersion(String filePath, String versionId) {
    logger.info("恢复文件到版本: " + filePath + " -> " + versionId);

    try {
      List<FileVersion> versions = getVersionHistory(filePath);
      FileVersion targetVersion =
          versions.stream()
              .filter(v -> v.getVersionId().equals(versionId))
              .findFirst()
              .orElse(null);

      if (targetVersion == null) {
        logger.warn("版本不存在: " + versionId);
        return false;
      }

      // 在恢复前创建当前版本的备份
      createVersion(filePath, "恢复前自动备份");

      // 从备份文件恢复
      Path backupFile = Paths.get(targetVersion.getBackupPath());
      Path targetFile = Paths.get(filePath);

      if (!Files.exists(backupFile)) {
        logger.error("备份文件不存在: " + targetVersion.getBackupPath());
        return false;
      }

      Files.copy(backupFile, targetFile, StandardCopyOption.REPLACE_EXISTING);

      // 更新版本状态
      for (FileVersion version : versions) {
        version.setCurrent(version.getVersionId().equals(versionId));
      }

      logger.info("成功恢复文件版本: " + filePath);
      return true;

    } catch (Exception e) {
      logger.error("恢复文件版本失败: " + filePath, e);
      return false;
    }
  }

  /** 比较文件版本 */
  public FileDifference compareVersions(String filePath, String version1Id, String version2Id) {
    logger.debug("比较文件版本: " + filePath + " (" + version1Id + " vs " + version2Id + ")");

    FileDifference difference = new FileDifference(filePath, version1Id, version2Id);

    try {
      List<FileVersion> versions = getVersionHistory(filePath);

      FileVersion version1 =
          versions.stream()
              .filter(v -> v.getVersionId().equals(version1Id))
              .findFirst()
              .orElse(null);

      FileVersion version2 =
          versions.stream()
              .filter(v -> v.getVersionId().equals(version2Id))
              .findFirst()
              .orElse(null);

      if (version1 == null || version2 == null) {
        difference.setType(FileDifference.DifferenceType.BINARY_DIFFERENT);
        difference.setChanges(Arrays.asList("无法找到指定版本"));
        return difference;
      }

      // 比较校验和
      if (version1.getChecksum().equals(version2.getChecksum())) {
        difference.setIdentical(true);
        difference.setType(FileDifference.DifferenceType.IDENTICAL);
        difference.setChanges(Arrays.asList("文件内容完全相同"));
      } else {
        difference.setIdentical(false);
        difference.setSizeDifference(version2.getFileSize() - version1.getFileSize());

        if (version1.getFileSize() != version2.getFileSize()) {
          difference.setType(FileDifference.DifferenceType.SIZE_ONLY);
        } else {
          difference.setType(FileDifference.DifferenceType.CONTENT_CHANGED);
        }

        // 简化的差异分析
        List<String> changes = new ArrayList<>();
        changes.add("文件大小变化: " + formatSizeDifference(difference.getSizeDifference()));
        changes.add("版本1校验和: " + version1.getChecksum().substring(0, 16) + "...");
        changes.add("版本2校验和: " + version2.getChecksum().substring(0, 16) + "...");

        difference.setChanges(changes);
      }

    } catch (Exception e) {
      logger.error("比较文件版本失败", e);
      difference.setType(FileDifference.DifferenceType.BINARY_DIFFERENT);
      difference.setChanges(Arrays.asList("比较失败: " + e.getMessage()));
    }

    return difference;
  }

  /** 清理旧版本 */
  public int cleanupOldVersions() {
    logger.info("开始清理旧版本...");

    int deletedCount = 0;
    LocalDateTime cutoffTime = LocalDateTime.now().minusDays(30); // 保留30天内的版本

    for (Map.Entry<String, List<FileVersion>> entry : versionCache.entrySet()) {
      List<FileVersion> versions = entry.getValue();

      // 保留最新的5个版本和30天内的版本
      for (int i = 5; i < versions.size(); i++) {
        FileVersion version = versions.get(i);
        if (version.getCreatedTime().isBefore(cutoffTime)) {
          try {
            // 删除备份文件
            if (version.getBackupPath() != null) {
              Files.deleteIfExists(Paths.get(version.getBackupPath()));
            }
            versions.remove(i);
            deletedCount++;
            i--; // 调整索引
          } catch (Exception e) {
            logger.error("删除旧版本失败: " + version.getVersionId(), e);
          }
        }
      }
    }

    logger.info("清理完成，删除了 " + deletedCount + " 个旧版本");
    return deletedCount;
  }

  /** 关闭服务 */
  public void shutdown() {
    logger.info("文件版本服务正在关闭...");
    // 保存版本信息到磁盘（简化实现）
    versionCache.clear();
  }

  /** 创建备份文件 */
  private String createBackupFile(Path sourceFile, String versionId) throws IOException {
    String fileName = sourceFile.getFileName().toString();
    String backupFileName = versionId + "_" + fileName;
    Path backupPath = Paths.get(versionsDirectory, backupFileName);

    Files.copy(sourceFile, backupPath, StandardCopyOption.REPLACE_EXISTING);
    return backupPath.toString();
  }

  /** 从磁盘加载版本信息 */
  private List<FileVersion> loadVersionsFromDisk(String filePath) {
    // 简化实现，实际应从数据库或元数据文件加载
    return new ArrayList<>();
  }

  /** 格式化大小差异 */
  private String formatSizeDifference(long sizeDiff) {
    if (sizeDiff == 0) {
      return "无变化";
    } else if (sizeDiff > 0) {
      return "增加 " + formatBytes(sizeDiff);
    } else {
      return "减少 " + formatBytes(-sizeDiff);
    }
  }

  /** 格式化字节数 */
  private String formatBytes(long bytes) {
    if (bytes < 1024) return bytes + " B";
    int exp = (int) (Math.log(bytes) / Math.log(1024));
    String pre = "KMGTPE".charAt(exp - 1) + "";
    return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);
  }
}
